package com.jstyle.jclife.activity;

import android.app.Activity;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter.LeScanCallback;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.AnimationDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.jstyle.jclife.R;
import com.jstyle.jclife.model.BleData;
import com.jstyle.jclife.utils.RxBus;
import com.jstyle.jclife.utils.SharedPreferenceUtils;

import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.dfu.DfuBaseService;
import no.nordicsemi.android.dfu.DfuServiceInitiator;
import no.nordicsemi.android.error.GattError;


public class OtaActivity extends Activity implements OnClickListener {
    private static final String EXTRA_URI = "uri";
    @BindView(R.id.iv_update_circle)
    ImageView ivUpdateCircle;
    private BluetoothAdapter mAdapter;
    private String mFilePath;
    private Uri mFileStreamUri;
    private Handler handler = new Handler();

    private ProgressBar mProgressBar;
    private TextView mTextPercentage;
    private ProgressDialog dialog;

    protected String version;

    public static final String EXTRA_FILE_URI = "jstyle.dfu.extra.EXTRA_FILE_URI";
    public static final String EXTRA_FILE_PATH = "jstyle.dfu.extra.EXTRA_FILE_PATH";

    private String deviceAddress;//设备mac地址，搜索到这个表示设备未进入dfu模式，或者已经从dfu模式恢复


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_otafile);
        ButterKnife.bind(this);
        Log.i(TAG, "onCreate: ");
        BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        mAdapter = manager.getAdapter();
        IntentFilter filter = new IntentFilter();
        filter.addAction(DfuBaseService.BROADCAST_PROGRESS);
        filter.addAction(DfuBaseService.BROADCAST_ERROR);
        filter.addAction("onDescriptorWrite");
        mFilePath = getIntent().getStringExtra(EXTRA_FILE_PATH);
        Log.i(TAG, "onCreate: " + mFilePath);
        mFileStreamUri = getIntent().getParcelableExtra(EXTRA_FILE_URI);
        //deviceAddress =getIntent().getStringExtra(MainActivity.Device_Address);
        final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
        broadcastManager.registerReceiver(mDfuUpdateReceiver, filter);
        registerReceiver(mDfuUpdateReceiver, filter);
        startScan(true);
        initView();

    }

    private void initView() {

        dialog = new ProgressDialog(this);
        dialog.setTitle("Please wait.....");
        dialog.setCanceledOnTouchOutside(false);
        mTextPercentage = (TextView) findViewById(R.id.textviewProgress);
        mProgressBar = (ProgressBar) findViewById(R.id.progressbar_file);
        AnimationDrawable animationDrawableUpdate = (AnimationDrawable) ivUpdateCircle.getDrawable();
        animationDrawableUpdate.start();
        //	if(device.deviceName.equals("DfuTarg")){
        //		sendHex(device.deviceName,device.deviceMac);
        //	}
    }


    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {

        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);

    }

    private static final int SELECT_FILE_REQ = 1;
    static final int REQUEST_ENABLE_BT = 2;

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.i(TAG, "onDestroy: ");
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
        manager.unregisterReceiver(mDfuUpdateReceiver);
        unregisterReceiver(mDfuUpdateReceiver);
        if (handler != null) handler.removeCallbacksAndMessages(null);

    }


    public static final String Action_Dfu_Complete = "Action_Dfu_Complete";
    public static final String Action_Dfu_Failed = "Action_Dfu_Failed";
    public static final String Action_EnterDfuMode_Failed = "Action_EnterDfuMode_Failed";
    private final BroadcastReceiver mDfuUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            // DFU is in progress or an error occurred
            final String action = intent.getAction();

            if (DfuBaseService.BROADCAST_PROGRESS.equals(action)) {

                final int progress = intent.getIntExtra(
                        DfuBaseService.EXTRA_DATA, 0);
                final int currentPart = intent.getIntExtra(
                        DfuBaseService.EXTRA_PART_CURRENT, 1);
                final int totalParts = intent.getIntExtra(
                        DfuBaseService.EXTRA_PARTS_TOTAL, 1);

                updateProgressBar(progress, currentPart, totalParts, false);

            } else if (DfuBaseService.BROADCAST_ERROR.equals(action)) {
                final int error = intent.getIntExtra(DfuBaseService.EXTRA_DATA,
                        0);
                //showErrorMessage(error);
                Log.i(TAG, "onReceive: " + error);
                dialog.cancel();
                updateProgressBar(error, 0, 0, true);

                // We have to wait a bit before canceling notification. This is
                // called before DfuService creates the last notification.
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        // if this activity is still open and upload process was
                        // completed, cancel the notification
                        final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                        manager.cancel(DfuBaseService.NOTIFICATION_ID);
                    }
                }, 200);
            }
        }
    };

    private void updateProgressBar(final int progress, final int part, final int total, final boolean error) {
        switch (progress) {
            case DfuBaseService.PROGRESS_CONNECTING:
                dialog.cancel();
                mProgressBar.setVisibility(View.VISIBLE);
                mTextPercentage.setVisibility(View.VISIBLE);
                mProgressBar.setIndeterminate(true);
                mTextPercentage.setText(R.string.dfu_status_connecting);
                break;
            case DfuBaseService.PROGRESS_STARTING:
                mProgressBar.setIndeterminate(true);
                mTextPercentage.setText(R.string.dfu_status_starting);
                break;
            case DfuBaseService.PROGRESS_ENABLING_DFU_MODE:
                mProgressBar.setIndeterminate(true);
                mTextPercentage.setText(R.string.dfu_status_switching_to_dfu);
                break;
            case DfuBaseService.PROGRESS_VALIDATING:
                mProgressBar.setIndeterminate(true);
                mTextPercentage.setText(R.string.dfu_status_validating);
                break;
            case DfuBaseService.PROGRESS_DISCONNECTING:
                mProgressBar.setIndeterminate(true);
                mTextPercentage.setText(R.string.dfu_status_disconnecting);
                break;
            case DfuBaseService.PROGRESS_COMPLETED:
                mTextPercentage.setText(R.string.dfu_status_completed);
                // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        onTransferCompleted();
                        //isOtaSuccess=true;
                    }
                }, 200);
                break;
            case DfuBaseService.PROGRESS_ABORTED:
                mTextPercentage.setText(R.string.dfu_status_aborted);
                // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.

                break;
            default:
                mProgressBar.setIndeterminate(false);
                if (error) {
                    showErrorMessage(progress);
                } else {
                    mProgressBar.setProgress(progress);
                    //Log.i(TAG, "updateProgressBar: "+progress);
                    mTextPercentage.setText(getString(R.string.progress, progress));
//				if (total > 1)
//					mTextUploading.setText(getString(R.string.dfu_status_uploading_part, part, total));
//				else
//					mTextUploading.setText(R.string.dfu_status_uploading);
                }
                break;
        }
    }

    private void showErrorMessage(int code) {
        // TODO Auto-generated method stub
        String result = GattError.parse(code) + " (" + (code & ~(DfuBaseService.ERROR_MASK | DfuBaseService.ERROR_REMOTE_MASK)) + ")";
        //	showToast("Upload failed: " + result);
        sendDfuAction(Action_Dfu_Failed, result);
    }

    protected void showToast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }

    protected void checkUpDate() {
        // TODO Auto-generated method stub
        //	device.checkUpdate();
    }

    protected void onTransferCompleted() {
        mProgressBar.setVisibility(View.INVISIBLE);
        mTextPercentage.setVisibility(View.INVISIBLE);
        Toast.makeText(this, R.string.ota_success, Toast.LENGTH_SHORT).show();
        SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_DFU_ADDRESS,"");
        sendDfuAction(Action_Dfu_Complete);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                // if this activity is still open and upload process was
                // completed, cancel the notification
                final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                manager.cancel(DfuBaseService.NOTIFICATION_ID);
            }
        }, 200);

        //	showRestDialog();
        //	device.reConnected();
    }

    private void sendDfuAction(String action, String data) {
        RxBus rxBus = RxBus.getInstance();
        BleData bleData = new BleData();
        bleData.setData(data);
        bleData.setAction(action);
        rxBus.post(bleData);
        finish();
    }

    private void sendDfuAction(String action) {
        RxBus rxBus = RxBus.getInstance();
        BleData bleData = new BleData();
        bleData.setAction(action);
        rxBus.post(bleData);
        finish();
    }

    private static final String TAG = "OtaActivity";
    private boolean isStart;//防止扫描速度过快导致重复进入dfubaservice
    private LeScanCallback callback = new LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, int arg1, byte[] arg2) {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    final String name = device.getName();
                    final String address = device.getAddress();
                    Log.i(TAG, "run: " + address);
                    if (!TextUtils.isEmpty(deviceAddress) && address.equals(deviceAddress)) {
                        startScan(false);
                        sendDfuAction(Action_EnterDfuMode_Failed);
                        return;
                    }
                    if (name != null && name.toLowerCase().contains("dfu") && !isStart) {
                        isStart = true;
                        startScan(false);
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                sendHex(name, address);
                            }
                        }, 2000);
                    }

                }

            });

        }
    };

    private void sendHex(String name, String address) {
        if (TextUtils.isEmpty(mFilePath) && mFileStreamUri == null) return;
        final DfuServiceInitiator starter = new DfuServiceInitiator(address)
                .setDeviceName(name)
                .setKeepBond(false)
                .setForceDfu(false)
                .setPacketsReceiptNotificationsEnabled(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
                .setPacketsReceiptNotificationsValue(DfuServiceInitiator.DEFAULT_PRN_VALUE)
                .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
        if (!TextUtils.isEmpty(mFilePath)) {
            if (mFilePath.endsWith("zip")) {
                starter.setZip(mFileStreamUri, mFilePath);
            } else {
                starter.setBinOrHex(DfuBaseService.TYPE_APPLICATION, mFileStreamUri, mFilePath);
            }
        } else {
            starter.setZip(mFileStreamUri, mFilePath);
        }
        SharedPreferenceUtils.setSpString(SharedPreferenceUtils.KEY_DFU_ADDRESS,address);
        starter.start(this, DfuService.class);

    }

    protected void startScan(boolean b) {
        if (b) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {    // TODO Auto-generated method stub
                    mAdapter.stopLeScan(callback);
                    //Log.i(TAG, "run: 扫描超时");
                    sendDfuAction(Action_Dfu_Failed, "扫描超时");
                    Log.i(TAG, "startScan: stop超时");
                }
            }, 20000);
            Log.i(TAG, "startScan: start");
            mAdapter.startLeScan(callback);
        } else {
            Log.i(TAG, "startScan: stop");
            mAdapter.stopLeScan(callback);
            handler.removeCallbacksAndMessages(null);
        }
    }



    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_BACK){
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }
}
